#include "multiwidget.h"
#include "dm/dmdef.h"

#include <algorithm>

MultiWidget::MultiWidget(int decimal, double step, double min, double max, const QString &suffix, QWidget *parent)
    : AWidget{parent}
    , m_decimal{decimal}
    , m_step{step}
    , m_min{min}
    , m_max{max}
    , m_suffix{suffix}
    , m_switch{false}
    , m_value{m_min}
{
    setFixedSize(100, 30);
    setAttribute(Qt::WA_TranslucentBackground);
    setMouseTracking(true);
    // setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    edit = new ALineEdit(this);
    edit->setValidator(new QDoubleValidator(m_min, m_max, m_decimal, this));
    edit->setFixedSize(90, 16);
    edit->setFrame(false);
    edit->setStyleSheet(R"(
        ALineEdit {
            border: none;
            background: transparent;
            color: #FFFFFF;
        }
    )");

    auto layout = new QVBoxLayout(this);
    layout->addWidget(edit, Qt::AlignVCenter);
    layout->setContentsMargins(0, 0, 0, 0);

    connect(edit, &ALineEdit::textConfirmed, this, [=](const QString &text) {
        set(text.toDouble());
    });

    m_upRect = {false, false, QRectF(1, 1, edit->size().width() - 2, height() * 0.25 - 2)};
    m_downRect = {false, false, QRectF(QPointF(m_upRect.rect.x(), height() * 0.75), m_upRect.rect.size())};
    m_onRect = {false, false, QRectF(m_upRect.rect.topRight(), QSizeF(width() - edit->size().width(), height() * 0.5))};
    m_offRect = {false, false, QRectF(m_onRect.rect.bottomLeft(), m_onRect.rect.size())};

    set(m_value);
}

void MultiWidget::set(const double &value)
{
    if (value > m_max || value < m_min) {
        return;
    }
    m_value = std::clamp(value, m_min, m_max);
    m_switch = (m_min != m_value);
    if (m_switch) {
        edit->setText(QString::number(m_value) + tr(LABEL_DECIBEL_UINT));
    }
    else {
        edit->setText(tr(LABEL_OFF));
    }
    emit valueChanged(m_value);
    update();
}

void MultiWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);

    auto pen = painter.pen();
    const auto defualtColor = pen.color();
    const QColor enterColor(137, 207, 240, 128);
    pen.setColor(defualtColor);
    painter.setPen(pen);
    // 外框
    QRectF out(1, 1, width() - 2, height() - 2);
    painter.drawRoundedRect(out, 5, 5);

    // 值区
    QRectF left(m_upRect.rect.topLeft(), QSizeF(m_upRect.rect.width(), out.height()));
    // 开关区
    QRectF right(left.topRight(), QSizeF(m_onRect.rect.width(), left.height()));
    // painter.drawRoundedRect(left, 5, 5);
    painter.drawRoundedRect(right, 5, 5);

    // 上箭头
    if (m_upRect.enter) {
        pen.setColor(enterColor);
    }
    else {
        pen.setColor(defualtColor);
    }
    painter.setPen(pen);
    const double offset = m_upRect.rect.height() / 2;
    QPointF up(m_upRect.rect.center().x(), m_upRect.rect.y() + offset);
    QPointF upleft(up.x() - offset, up.y() + offset);
    QPointF upright(up.x() + offset, upleft.y());
    painter.drawLine(upleft, up);
    painter.drawLine(up, upright);
    // 下箭头
    if (m_downRect.enter) {
        pen.setColor(enterColor);
    }
    else {
        pen.setColor(defualtColor);
    }
    painter.setPen(pen);
    QPointF down(m_downRect.rect.center().x(), m_downRect.rect.bottomLeft().y() - offset);
    QPointF downleft(down.x() - offset, down.y() - offset);
    QPointF downright(down.x() + offset, downleft.y());
    painter.drawLine(downleft, down);
    painter.drawLine(down, downright);
    pen.setColor(defualtColor);
    painter.setPen(pen);
    // 开关
    constexpr double radius = 5;
    QRectF on(right.topLeft(), QSizeF(right.width(), right.height() / 2));
    QRectF off(on.bottomLeft(), on.size());
    if (m_switch) {
        painter.setBrush(QColor(47, 140, 0));
        painter.drawRoundedRect(on, radius, radius);
    }
    else {
        painter.setBrush(QColor(204, 49, 49));
        painter.drawRoundedRect(off, radius, radius);
    }
    painter.setBrush(Qt::NoBrush);
}

void MultiWidget::wheelEvent(QWheelEvent *event)
{
    Q_UNUSED(event);
    if (event->angleDelta().y() > 0) {
        set(m_value + 1);
    }
    else {
        set(m_value - 1);
    }
}

void MultiWidget::mousePressEvent(QMouseEvent *event)
{
    m_upRect.press = m_upRect.rect.contains(event->pos());
    m_downRect.press = m_downRect.rect.contains(event->pos());
    m_onRect.press = m_onRect.rect.contains(event->pos());
    m_offRect.press = m_offRect.rect.contains(event->pos());
    event->accept();
}

void MultiWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if (m_upRect.press && m_upRect.rect.contains(event->pos())) {
        set(m_value + 1);
        return;
    }
    if (m_downRect.press && m_downRect.rect.contains(event->pos())) {
        set(m_value - 1);
        return;
    }
    if (m_onRect.press && m_onRect.rect.contains(event->pos()) && !m_switch) {
        set(m_max);
        return;
    }
    if (m_offRect.press && m_offRect.rect.contains(event->pos()) && m_switch) {
        set(m_min);
        return;
    }
    event->accept();
}

void MultiWidget::mouseMoveEvent(QMouseEvent *event)
{
    m_upRect.enter = m_upRect.rect.contains(event->pos());
    m_downRect.enter = m_downRect.rect.contains(event->pos());
    m_onRect.enter = m_onRect.rect.contains(event->pos());
    m_offRect.enter = m_offRect.rect.contains(event->pos());
    event->accept();
    update();
}
